﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LogLib;
using ComLib.ComFun;
using System.Collections;
using ComLib.ComType;
using System.Reflection;
using System.IO;
using PixelDetectSDKInterface;

namespace DetectProcessing
{
    /// <summary>
    /// 像素处理者工厂服务类
    /// </summary>
    public class PixelDetectFactory : IDisposable
    {
        #region static field and functions
        private static object _lock = new object();

        protected static PixelDetectFactory _instance;
        public static PixelDetectFactory Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_lock)
                    {
                        if (_instance == null)
                        {
                            _instance = new PixelDetectFactory();
                        }
                    }
                }
                return _instance;
            }
        }
        #endregion

        private bool _bInitOK = false;
        public bool InitOK
        {
            get { return _bInitOK; }
            set { _bInitOK = value; }
        }

        private List<IntPtr> _listPxlHandles = new List<IntPtr>();

        private Dictionary<ApplyTo, IntPtr> DetectHandles = new Dictionary<ApplyTo, IntPtr>();

        /// <summary>
        /// 照片类型和对应处理标准的映射集合
        /// </summary>
        private Dictionary<ApplyTo, string> MapPxlStd = new Dictionary<ApplyTo, string>();


        private Dictionary<IntPtr, _FGImageDetectStdData> MapStdData = new Dictionary<IntPtr, _FGImageDetectStdData>();

        /// <summary>
        /// 同步锁对象
        /// </summary>
        private static object _lockObj = new object();
  
        /// <summary>
        /// 错误信息
        /// </summary>
        private string _errorMessage = "";
        public string ErrorMessage
        {
            get { return _errorMessage; }
            set { _errorMessage = value; }
        }

        private PixelDetectFactory()
        {
            InitStdMap();
        }

        private void InitStdMap()
        {
            MapPxlStd.Clear();
            MapPxlStd.Add(ApplyTo.ExitAndEntry, PxlFltPath.ExitAndEntry);
            MapPxlStd.Add(ApplyTo.PortVisa, PxlFltPath.PortVisa);
            MapPxlStd.Add(ApplyTo.IDCard, PxlFltPath.SFZ);
            MapPxlStd.Add(ApplyTo.SocialSecurity, PxlFltPath.SocialSecurity);
            MapPxlStd.Add(ApplyTo.DrivingLicence, PxlFltPath.JSZ);
        }

        public bool Init()
        {
            try
            {
                int ret = DetectSDKInterface.InitDetectSdk();
                if (ret != 0)
                {
                    _errorMessage = "初始化PxlDetectSDK失败:" + DetectHandleResult.ParseErrorMessage(ret);
                    Log.WriteAsync(_errorMessage);
                    _bInitOK = false;
                    return false;
                }
                Log.WriteAsync("PXL类库初始化成功.");
                _bInitOK = true;
                return true;
            }
            catch (Exception ex)
            {
                Log.WriteException(ex.ToString());
                _errorMessage = "初始化PxlDetectSDK发生了异常:" + ex.Message;
                _bInitOK = false;
                return false;
            }          
        }

        /// <summary>
        /// 创建像素算法识别句柄
        /// </summary>
        private IntPtr CreateDetectPxlHandler(string fileKeyName)
        {          
            _errorMessage = "";
            string directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase);
            directory = directory.Substring(6);
            lock (_lockObj)
            {             
                string stdFile = string.Format(@"{0}\PixelDetectSDK\{1}.flt", directory, fileKeyName);
                IntPtr hDetect = IntPtr.Zero;
                // 创建算法识别句柄         
                string modelsPath = Path.Combine(directory, "models");
                int ret = DetectSDKInterface.CreateImageDetectHandle(ref hDetect, modelsPath);              
                if (ret != 0)
                {
                    _errorMessage = string.Format("DetectSDK句柄创建失败: {0}", DetectHandleResult.ParseErrorMessage(ret));
                    Log.WriteAsync(_errorMessage);
                    throw new Exception(_errorMessage);
                }
                byte[] readArray = ComFun.ReadByteArray(stdFile);
                ret = DetectSDKInterface.LoadStd(hDetect, readArray, readArray.Length);               
                if (ret != 0)
                {
                    _errorMessage = string.Format("PXL标准文件({0})加载失败: {1}", stdFile, DetectHandleResult.ParseErrorMessage(ret));
                    Log.WriteAsync(_errorMessage);
                    throw new Exception(_errorMessage);
                }
                Log.WriteAsync("PXL检测句柄已创建, 加载标准文件来自: " + stdFile);
                _listPxlHandles.Add(hDetect);

                _FGImageDetectStdData stdData = new _FGImageDetectStdData();
                ret = PixelDetectSDK.GetStdData(hDetect, out stdData);
                if (ret != 0)
                {
                    _errorMessage = string.Format("检测标准{0}读取失败: {1}", stdFile, DetectHandleResult.ParseErrorMessage(ret));
                    Log.WriteAsync(_errorMessage);
                    throw new Exception(_errorMessage);
                }
                MapStdData.Add(hDetect, stdData);
                return hDetect;
            }         
        }

        public _FGImageDetectStdData GetStdData(IntPtr handle)
        {
            if (MapStdData.ContainsKey(handle))
            {
                return MapStdData[handle];
            }
            else
            {
                throw new Exception("获取检测标准失败: 无效的句柄");
            }
        }

        public IntPtr this[ApplyTo key]
        {
            get
            {
                if (!MapPxlStd.ContainsKey(key))
                {
                    string logInfo = string.Format("制证类型不存在:{0}", key);
                    Log.WriteAsync(logInfo);
                    return IntPtr.Zero;
                }
                if (!DetectHandles.ContainsKey(key))
                {
                    IntPtr hDetect = CreateDetectPxlHandler(MapPxlStd[key]);
                    string logInfo = string.Format("创建了新的检测句柄:{0}, {1}", hDetect, key);
                    Log.WriteAsync(logInfo);
                    if (hDetect == IntPtr.Zero)
                    {
                        throw new Exception(ErrorMessage);
                    }
                    _listPxlHandles.Add(hDetect);
                    DetectHandles.Add(key, hDetect);
                    return hDetect;
                }
                else
                {
                    return DetectHandles[key];
                }
            }
        }

        public void Dispose()
        {
            for (int i = 0; i < _listPxlHandles.Count; i++)
            {
                IntPtr hDetect = _listPxlHandles[i];
                if (_listPxlHandles[i] != IntPtr.Zero)
                {
                    string logInfo = string.Format("释放检测句柄:{0}", hDetect);
                    Log.WriteAsync(logInfo);
                    DetectSDKInterface.DestroyImageDetectHandle(hDetect);
                    _listPxlHandles[i] = IntPtr.Zero;
                }
            }
            _listPxlHandles.Clear();
            DetectHandles.Clear();
        }
    }
}
